package article

import (
	"context"
	"errors"
	"github.com/bwmarrin/snowflake"
	"github.com/gin-gonic/gin"
	"go.mongodb.org/mongo-driver/bson"
	"go.mongodb.org/mongo-driver/mongo"
	"go.mongodb.org/mongo-driver/mongo/options"
	"time"
)

type MongoDBDAO struct {
	//client   *mongo.Client
	//database *mongo.Database
	//代表制作库
	col *mongo.Collection
	//代表线上库
	liveCol *mongo.Collection

	node *snowflake.Node
}

func NewMongoDBDAO(database *mongo.Database, node *snowflake.Node) *MongoDBDAO {
	return &MongoDBDAO{
		col:     database.Collection("articles"),
		liveCol: database.Collection("publish_articles"),
		node:    node,
	}
}

func (m *MongoDBDAO) Insert(ctx context.Context, art Article) (int64, error) {
	now := time.Now().UnixMilli()
	art.Ctime = now
	art.Utime = now
	id := m.node.Generate().Int64()
	art.Id = id
	_, err := m.col.InsertOne(ctx, art)
	if err != nil {
		return 0, err
	}
	return id, err
}

func (m *MongoDBDAO) UpdateById(ctx context.Context, art Article) error {
	filter := bson.M{"id": art.Id, "author_id": art.AuthorId}
	update := bson.D{bson.E{"$set", bson.M{
		"title":   art.Title,
		"content": art.Content,
		"utime":   art.Utime,
		"status":  art.Status,
	}}}
	res, err := m.col.UpdateOne(ctx, filter, update)
	if err != nil {
		return err
	}
	if res.ModifiedCount == 0 {
		return errors.New("更新数据失败")
	}
	return err
}

func (m *MongoDBDAO) Sync(ctx context.Context, art Article) (int64, error) {
	var (
		id  = art.Id
		err error
	)
	if id > 0 {
		err = m.UpdateById(ctx, art)
	} else {
		id, err = m.Insert(ctx, art)
	}
	if err != nil {
		return 0, err
	}
	art.Id = id
	now := time.Now().UnixMilli()
	//操作线上库 upsert
	art.Utime = now
	update := bson.E{"$set", PublishedArticle{art}}
	upsert := bson.E{"$setOnInsert", bson.D{bson.E{"ctime", now}}}
	filter := bson.M{"id": id}

	//map的实现
	//updateV1 := bson.M{
	//	"$set": PublishedArticle{art},
	//	"$setOnInsert":bson.M{"ctime":now},
	//}
	//_, err = m.liveCol.UpdateOne(ctx, filter, updateV1, options.Update().SetUpsert(true))

	_, err = m.liveCol.UpdateOne(ctx, filter, bson.D{update, upsert}, options.Update().SetUpsert(true))

	return id, err
}

func (m *MongoDBDAO) Upsert(ctx context.Context, art PublishedArticle) error {
	//TODO implement me
	panic("implement me")
}

func (m *MongoDBDAO) SyncStatus(ctx *gin.Context, id int64, authorId int64, status uint8) error {
	//TODO implement me
	panic("implement me")
}
